using System;
using System.Collections.Generic;
using SolarWinds.Logic;
using Lidgren.Network;

namespace SolarWinds.Networking
{
    public class Server
    {
        private NetServer server;
        private NetBuffer buffer;

        private readonly Dictionary<String, Player> mName2PlayersDict = new Dictionary<String, Player>();

        public void Initialize()
        {
            // create a configuration for the server
            NetConfiguration config = new NetConfiguration("SolarWinds");
            config.MaxConnections = 128;
            config.Port = 8930;

            // create server and start listening for connections
            server = new NetServer(config);
            server.SetMessageTypeEnabled(NetMessageType.ConnectionApproval, true);
            server.Start();

            // create a buffer to read data into
            buffer = server.CreateBuffer();            
        }

        public void Shutdown()
        {
            server.Shutdown("Server is shutting down");
        }

        public void Update()
        {
            NetMessageType type;
            NetConnection sender;

            // check if any messages has been received
            while (server.ReadMessage(buffer, out type, out sender))
            {
                switch (type)
                {
                    case NetMessageType.DebugMessage:
                        Console.WriteLine("[Server] " + buffer.ReadString());
                        break;
                    case NetMessageType.ConnectionApproval:
                        Console.WriteLine("[Server] Approval; hail is " + buffer.ReadString());
                        sender.Approve();
                        break;
                    case NetMessageType.StatusChanged:
                        Console.WriteLine("[Server] New status for " + sender + ": " + sender.Status + " (" + buffer.ReadString() + ")");
                        break;
                    case NetMessageType.Data:
                        Console.WriteLine("[Server] Data received from " + sender);
                        
                        MessageTypes msgType = (MessageTypes)buffer.ReadInt32();
                        if (msgType == MessageTypes.PLAYER_JOINED)
                        {
                            PlayerJoinedMessage msg = new PlayerJoinedMessage();
                            msg.FromBuffer(buffer);

                            PlayerJoined(msg);
                        }
                        break;
                }
            }
        }

        public void SendToAll(NetworkMessage msg)
        {
            // Send message
            NetBuffer sendBuffer = new NetBuffer();
            msg.ToBuffer(sendBuffer);
            server.SendToAll(sendBuffer, NetChannel.ReliableInOrder1);
        }

        public void PlayerJoined(PlayerJoinedMessage msg)
        {
            // check if player already exists
            if (mName2PlayersDict.ContainsKey(msg.mPlayerName))
            {
                // TODO send a message to the sender
            }
            else
            {
                // register player and send message to all players
                mName2PlayersDict.Add(msg.mPlayerName, new Player(msg.mPlayerName));

                foreach (KeyValuePair<String, Player> pair in mName2PlayersDict)
                {
                    Console.WriteLine("[Server] Players: " + pair.Key);
                }

                SendToAll(msg);
            }
        }

        public void PlayerLeft()
        {

        }

        public void PlayerMoved()
        {

        }
    }
}